<template></template>
<script setup>
import { onMounted } from 'vue'
import mitter from '@/utils/eventBus.js'

// WebSocket心跳机制的原理是利用心跳包及时发送和接收数据，每隔一段时间发送一次消息用于维持链接，保证WebSocket长连接不被断开。WebSocket心跳机制的原理可以用下面的流程来说明：
// 1.客户端建立WebSocket连接。
// 2.客户端向服务器发送心跳数据包，服务器接收并返回一个表示接收到心跳数据包的响应。
// 3.当服务器没有及时接收到客户端发送的心跳数据包时，服务器会发送一个关闭连接的请求。
// 4.服务器定时向客户端发送心跳数据包，客户端接收并返回一个表示接收到心跳数据包的响应。
// 5.当客户端没有及时接收到服务器发送的心跳数据包时，客户端会重新连接WebSocket。

//心跳
const heartCheck = {
    timeout: 5000,
    clientTimeout: null,
    serverTimeout: null,
    reset: function () {
        window.clearTimeout(this.clientTimeout)
        window.clearTimeout(this.serverTimeout)
    },
    start: function () {
        const self = this
        this.clientTimeout = window.setTimeout(() => {
            socket.send('心跳')
            //收到消息后会清除所有定时器，且重新开启心跳，在心跳期间未收到消息，serverTimeout将执行：关闭连接
            self.serverTimeout = window.setTimeout(() => {
                // 关闭连接
                socket.close()
            }, self.timeout)
        }, self.timeout)
    }
}
//socket对象
let socket = null
const connectInit = () => {
    //初次连接
    socket = new WebSocket('ws://192.168.3.66:8099/websocket')
    //初始化监听
    listenInit()
}
//发送消息
const sendMessage = (data) => {
    if (!data) return
    if (typeof data !== 'string') socket.send(JSON.stringify(data))
    else socket.send(data)
}

//连接成功
const open = () => {
    mitter.on('socketSend', sendMessage)
    // 连接成功后立刻开启心跳
    heartCheck.start(socket)
}
// 收到消息
const message = (message) => {
    console.log(message.data)
    // webSocket心跳重置：收到消息清除所有定时器
    heartCheck.reset()
    // webSocket重新开启心跳
    heartCheck.start()
}
// 解除事件监听
const removeEventListener = () => {
    socket.removeEventListener('open', open)
    socket.removeEventListener('message', message)
    socket.removeEventListener('close', close)
    socket.removeEventListener('error', error)
}
// 连接关闭
const close = (event) => {
    console.log('连接已关闭', event)
    removeEventListener()
    // 连接关闭，重新发起连接
    connectInit()
    mitter.off('socketSend', sendMessage)
}
// 连接失败
const error = (event) => {
    console.log('websocket连接失败', event)
}
// 初始化socket对象监听事件
const listenInit = () => {
    socket.addEventListener('open', open)

    socket.addEventListener('message', message)

    socket.addEventListener('close', close)

    socket.addEventListener('error', error)
}
onMounted(() => {
    connectInit()
})

</script>